#include "../header/district.h"
#include "../header/shape.h"
#include "../header/city.h"

#define D false

int LandQuad::nbQuad = 0;

// ============================================== //
// ================== LAND QUAD ================= //
// ============================================== //

void LandQuad::Subdivide()
{
	double min = std::min(std::min(std::min(Norm(p[1] - p[0]),Norm(p[1] - p[2])),Norm(p[2] - p[3])),Norm(p[3] - p[0]));
	double max = std::max(std::max(std::max(Norm(p[1] - p[0]),Norm(p[1] - p[2])),Norm(p[2] - p[3])),Norm(p[3] - p[0]));
	
	Quadrangle q = Quadrangle(p[0],p[1],p[2],p[3]);
	Vector a = p[0], b = p[1], c = p[2], d = p[3];

	if (max <= 10 || min < 5)
	{
		LandQuad(a, b, c, d).Show(q, D);
		nbQuad++;
	}
	else if (max <= 20)
	{
		int rand = std::rand() % 5;
		if (rand != 0)
			LandQuad(a,b,c,d).DiviseIrreg();
		else
		{
			LandQuad(a, b, c, d).Show(q, D);
			nbQuad++;
		}
	}
	else if (max <= 100)
		LandQuad(a,b,c,d).DiviseTrois();
	else if (max < 500)
		LandQuad(a,b,c,d).DiviseIrreg();
	else
		LandQuad(a,b,c,d).DiviseReg();
}

void LandQuad::Show(Quadrangle q, bool district)
{
	Quadrangle quad = q.Shrink(0.4, 0.4, 0.4, 0.4);

	Vector vect0 = quad[0];
	Vector vect1 = quad[1];
	Vector vect2 = quad[2];
	Vector vect3 = quad[3];

	if (district)
		PrismQuad(vect0, vect1, vect2, vect3, 0).Render();
	else
		BlockQuad(vect0, vect1, vect2, vect3).Subdivide();
}

void LandQuad::DiviseReg()
{
    Vector AB = (p[0] + p[1]) / 2;
	Vector CD = (p[2] + p[3]) / 2;
	Vector BC = (p[1] + p[2]) / 2;
	Vector AD = (p[0] + p[3]) / 2;
	Vector ABCD = (AB + CD) / 2;

	LandQuad(p[0],AB,ABCD,AD).Subdivide();
	LandQuad(AB,p[1],BC,ABCD).Subdivide();
	LandQuad(ABCD,BC,p[2],CD).Subdivide();
	LandQuad(AD,ABCD,CD,p[3]).Subdivide();	
}

void LandQuad::DiviseDeux()
{
	double max = std::max(std::max(std::max(Norm(p[1] - p[0]),Norm(p[1] - p[2])),Norm(p[2] - p[3])),Norm(p[3] - p[0]));

	if(max == Norm(p[1] - p[0]) || max == Norm(p[3] - p[2]))
	{
		 Vector AB = (p[0] + p[1]) / 2;
		 Vector CD = (p[2] + p[3]) / 2;

		 LandQuad(p[0],AB,CD,p[3]).Subdivide();
		 LandQuad(AB,p[1],p[2],CD).Subdivide();
	}
	else
	{
		Vector BC = (p[1] + p[2]) / 2;
		Vector AD = (p[0] + p[3]) / 2;
		LandQuad(p[0],p[1],BC,AD).Subdivide();
		LandQuad(AD,BC,p[2],p[3]).Subdivide();	
	}
}

void LandQuad::DiviseIrreg()
{
	double Xab = p[0][0] + 6*(p[1][0] - p[0][0]) / 10;
	double Yab = p[0][1] + 6*(p[1][1] - p[0][1]) / 10;
	Vector AB = Vector (Xab,Yab,0);

	double Xbc = p[1][0] + 6*(p[2][0] - p[1][0]) / 10;
	double Ybc = p[1][1] + 6*(p[2][1] - p[1][1]) / 10;
	Vector BC = Vector (Xbc,Ybc,0);

	double Xcd = p[2][0] + 6*(p[3][0] - p[2][0]) / 10;
	double Ycd = p[2][1] + 6*(p[3][1] - p[2][1]) / 10;
	Vector CD = Vector (Xcd,Ycd,0);

	double Xad = p[3][0] + 6*(p[0][0] - p[3][0]) / 10;
	double Yad = p[3][1] + 6*(p[0][1] - p[3][1]) / 10;
	Vector AD = Vector (Xad,Yad,0);
	
	double X = Xab + (Xcd - Xab) / 2;
	double Y = Yab + (Ycd - Yab) / 2;
	Vector M = Vector (X,Y,0);

	LandQuad(p[0],AB,M,AD).Subdivide();
	LandQuad(AB,p[1],BC,M).Subdivide();
	LandQuad(M,BC,p[2],CD).Subdivide();
	LandQuad(AD,M,CD,p[3]).Subdivide();
}

void LandQuad::DiviseTrois()
{
	double max = std::max(std::max(std::max(Norm(p[1] - p[0]),Norm(p[1] - p[2])),Norm(p[2] - p[3])),Norm(p[3] - p[0]));

	if(max == Norm(p[1] - p[0]) || max == Norm(p[3] - p[2]))
	{
		double Xab = p[0][0] + (p[1][0] - p[0][0]) / 3;
		double Yab = p[0][1] + (p[1][1] - p[0][1]) / 3;
		Vector AB = Vector (Xab,Yab,0);

		double Xcd = p[3][0] + (p[2][0] - p[3][0]) / 3;
		double Ycd = p[3][1] + (p[2][1] - p[3][1]) / 3;
		Vector CD = Vector (Xcd,Ycd,0);


		LandQuad(p[0],AB,CD,p[3]).Subdivide();
		LandQuad(AB,p[1],p[2],CD).Subdivide();
		
	}
	else
	{
		double Xbc = p[1][0] + (p[2][0] - p[1][0]) / 3;
		double Ybc = p[1][1] + (p[2][1] - p[1][1]) / 3;
		Vector BC = Vector (Xbc,Ybc,0);

		double Xad = p[0][0] + (p[3][0] - p[0][0]) / 3;
		double Yad = p[0][1] + (p[3][1] - p[0][1]) / 3;
		Vector AD = Vector (Xad,Yad,0);

		
		LandQuad(p[0],p[1],BC,AD).Subdivide();
		LandQuad(p[2],p[3],AD,BC).Subdivide();
		
	}
}
